﻿using System;
using System.Collections.Generic;
using System.Text;
using Graffiti.Core;
using RssToolkit.Rss;

namespace GraffitiExtras.Extensions.CommunityReactions
{
    [Chalk("reactions")]
    public class CommunityReactions
    {
        private const string googleRssUrl =
            "http://blogsearch.google.com/blogsearch_feeds?hl=en&q=link:{0}&ie=utf-8&num=100&output=rss";
        private const string technoratiRssUrl =
            "http://feeds.technorati.com/search/{0}";
        private const int feedUpdateInterval = 120;

        public string GetReactions(Post post, string notFoundText)
        {
            List<Reaction> initialReactions = new List<Reaction>();

            try
            {
                // Add Google results
                initialReactions.AddRange(GetGoogleReactions(post));
                // Add Technorati results
                initialReactions.AddRange(GetTechnorariReactions(post));
            }
            catch (Exception ex)
            {
                Log.Error("Error in Community Reactions Extension", ex.Message + ex.StackTrace);
            }

            // Remove duplicate items and sort final items by date
            List<Reaction> finalReactions = new List<Reaction>();
            finalReactions = FilterItems(initialReactions);

            // Generate the output and return it
            return GetHtml(finalReactions, notFoundText);
        }

        private List<Reaction> GetGoogleReactions(Post post)
        {
            string rssUrl = string.Format(googleRssUrl, new Macros().FullUrl(post.Url));

            List<Reaction> results = new List<Reaction>();

            try
            {
                Feed feed = new Feed();

                feed = FeedManager.GetFeed(rssUrl);

                if (feed == null)
                {
                    feed.Url = rssUrl;
                    feed.RequestInterval = feedUpdateInterval;

                    FeedManager.AddFeed(feed);
                    FeedManager.UpdateFeed(feed);

                    feed = FeedManager.GetFeed(rssUrl);
                }

                RssChannel channel = feed.Document.Channel;

                foreach (RssItem item in channel.Items)
                {
                    Reaction reaction = new Reaction(item.Title, item.Link,
                        DateTime.Parse(item.PubDate));
                    results.Add(reaction);
                }
            }
            catch (Exception ex)
            {
                Log.Error("Error in Community Reactions Extension", ex.Message + ex.StackTrace);
            }

            return results;
        }

        private List<Reaction> GetTechnorariReactions(Post post)
        {
            string rssUrl = string.Format(technoratiRssUrl, new Macros().FullUrl(post.Url));

            List<Reaction> results = new List<Reaction>();

            try
            {
                Feed feed = new Feed();

                feed = FeedManager.GetFeed(rssUrl);

                if (feed == null)
                {
                    feed.Url = rssUrl;
                    feed.RequestInterval = feedUpdateInterval;

                    FeedManager.AddFeed(feed);
                    FeedManager.UpdateFeed(feed);

                    feed = FeedManager.GetFeed(rssUrl);
                }

                RssChannel channel = feed.Document.Channel;

                foreach (RssItem item in channel.Items)
                {
                    Reaction reaction = new Reaction(item.Title, item.Link,
                        DateTime.Parse(item.PubDate));
                    results.Add(reaction);
                }
            }
            catch (Exception ex)
            {
                Log.Error("Error in Community Reactions Extension", ex.Message + ex.StackTrace);
            }

            return results;
        }

        private List<Reaction> FilterItems(List<Reaction> initialReactions)
        {
            List<Reaction> finalResults = new List<Reaction>();

            foreach (Reaction item in initialReactions)
            {
                if (!ContainsUrl(finalResults, item.Url))
                    finalResults.Add(item);
            }

            finalResults.Sort(delegate(Reaction reaction1, Reaction reaction2)
            {
                return Comparer<DateTime>.Default.Compare(reaction2.PubDate, reaction1.PubDate);
            });

            return finalResults;
        }

        private bool ContainsUrl(List<Reaction> reactions, string url)
        {
            foreach (Reaction item in reactions)
            {
                if (item.Url == url)
                    return true;
            }
            return false;
        }

        private string GetHtml(List<Reaction> finalReactions, string notFoundText)
        {
            if (finalReactions.Count > 0)
            {
                StringBuilder generator = new StringBuilder("<ul>");

                foreach (Reaction reaction in finalReactions)
                {
                    generator.AppendFormat("<li><a href='{0}' title='{1}'>{2}</a></li>",
                        reaction.Url, reaction.PubDate.ToLongDateString(), reaction.Title);
                }

                generator.Append("</ul>");

                return generator.ToString();
            }
            else
            {
                return notFoundText;
            }
        }
    }
}
